package com.qian.service.ddj.serviceImpl;


import com.alibaba.fastjson.JSONObject;
import com.qian.api.ddj.model.*;
import com.qian.api.ddj.service.IDaiFuOrderService;
import com.qian.api.ddj.service.IDfBusinessService;
import com.qian.api.ddj.service.IUserService;
import com.qian.service.ddj.dao.DaiFuOrderRepository;
import com.qian.service.ddj.dao.DfBusniessRepository;
import com.qian.service.ddj.dao.UserRepository;
import com.qian.service.ddj.entity.DdjDaiFuOrder;
import com.qian.service.ddj.entity.DdjDfBusiness;
import com.qian.service.ddj.entity.DdjUser;
import com.qian.service.ddj.util.HttpClient;
import com.qian.service.ddj.util.SignUtils;
import com.qian.service.ddj.util.YLutil.YLUtils.ApiUtils;
import com.qian.service.ddj.util.YLutil.YLUtils.HttpClientUtils;
import com.qian.service.ddj.util.YLutil.YLUtils.JsonUtils;
import com.yaowk.api.common.BaseException;
import com.yaowk.api.common.PageReq;
import com.yaowk.api.common.PageResp;
import com.yaowk.service.common.BaseRepository;
import com.yaowk.service.common.BaseServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.*;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Date;

import static com.qian.service.ddj.util.SignUtils.createSign;

@Slf4j
@Service
public class DaiFuOrderServiceImpl extends BaseServiceImpl<DaiFuOrder, DdjDaiFuOrder, Long> implements IDaiFuOrderService {

    private final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    private DaiFuOrderRepository dao;
    @Autowired
    private IUserService userService;
    @Autowired
    private IDfBusinessService businessService;
    @Autowired
    private DfBusniessRepository busniessDao;
    @Autowired
    private UserRepository userDao;


    @Override
    public PageResp<DaiFuOrder> findAll(final DfQueryModel model, PageReq pageReq) {
        PageRequest pageRequest = new PageRequest(pageReq.getPageNumber() - 1, pageReq.getPageSize(), new Sort(Sort.Direction.DESC, "createDate"));
        Long bt = System.currentTimeMillis();
        Page<DdjDaiFuOrder> page = dao.findAll(new Specification<DdjDaiFuOrder>() {
            @Override
            public Predicate toPredicate(Root<DdjDaiFuOrder> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Date> timePath = root.get("createDate");
                Path<Byte> statusPath = root.get("status");
                Predicate condition = criteriaBuilder.isNotNull(root.<Integer>get("id"));

                // 用户比较
                if (isNotEmpty(model.getUserId()))
                    condition = criteriaBuilder.and(condition, criteriaBuilder.equal(root.<Integer>get("userId"), model.getUserId()));
                // 状态比较
                if (isNotEmpty(model.getStatus()))
                    condition = criteriaBuilder.and(condition, criteriaBuilder.equal(statusPath, model.getStatus()));
                // 日期比较
                if (isNotEmpty(model.getBeginDate()) && isNotEmpty(model.getEndDate()))
                    condition = criteriaBuilder.and(condition, criteriaBuilder.between(timePath, model.getBeginDate(), model.getEndDate()));
                else if (isNotEmpty(model.getBeginDate()))
                    condition = criteriaBuilder.and(condition, criteriaBuilder.greaterThanOrEqualTo(timePath, model.getBeginDate()));
                else if (isNotEmpty(model.getEndDate()))
                    condition = criteriaBuilder.and(condition, criteriaBuilder.lessThanOrEqualTo(timePath, model.getEndDate()));
                // 商户比较
                if (isNotEmpty(model.getDfBusinessId()))
                    condition = criteriaBuilder.and(condition, criteriaBuilder.equal(root.<Integer>get("dfBusinessId"), model.getDfBusinessId()));
                return condition;
            }
        }, pageRequest);
        Long et = System.currentTimeMillis();
        logger.info("find order Time {}", et - bt);
        PageResp<DaiFuOrder> pageResp = page2pageResp(page);

        for (DaiFuOrder daiFuOrder : pageResp.getList()) {
            DdjUser user = userDao.findOne(daiFuOrder.getUserId());
            daiFuOrder.setUsername(user.getUsername());
            if (isNotEmpty(daiFuOrder.getDfBusinessId())) {
                DdjDfBusiness ddjBusiness = busniessDao.findOne(daiFuOrder.getDfBusinessId());
                daiFuOrder.setDfBusinessName(ddjBusiness.getName());
            }
        }

        return pageResp;
    }

    @Override
    public DaiFuOrder save(DaiFuOrder model) {
        if (model.isNew()) {
            model = entity2model(dao.save(model2Entity(model)));
        } else {
            DdjDaiFuOrder entity = dao.findOne(model.getId());
            if (isNotEmpty(model.getAmount())) {
                entity.setAmount(model.getAmount());
            }
            if (isNotEmpty(model.getBackup1())) {
                entity.setBackup1(model.getBackup1());
            }
            if (isNotEmpty(model.getBackup2())) {
                entity.setBackup2(model.getBackup2());
            }
            if (isNotEmpty(model.getBackup3())) {
                entity.setBackup3(model.getBackup3());
            }
            if (isNotEmpty(model.getBackup4())) {
                entity.setBackup5(model.getBackup5());
            }
            if (isNotEmpty(model.getBackup5())) {
                entity.setBackup5(model.getBackup5());
            }
            if (isNotEmpty(model.getBank())) {
                entity.setBank(model.getBank());
            }
            if (isNotEmpty(model.getCardNo())) {
                entity.setCardNo(model.getCardNo());
            }
            if (isNotEmpty(model.getFinishDate())) {
                entity.setFinishDate(model.getFinishDate());
            }
            if (isNotEmpty(model.getOutOrderNo())) {
                entity.setOutOrderNo(model.getOutOrderNo());
            }
            if (isNotEmpty(model.getUpOrderNo())) {
                entity.setUpOrderNo(model.getUpOrderNo());
            }
            if (isNotEmpty(model.getOrderNo())) {
                entity.setOrderNo(model.getOrderNo());
            }
            if (isNotEmpty(model.getPerson())) {
                entity.setPerson(model.getPerson());
            }
            if (isNotEmpty(model.getPhone())) {
                entity.setPhone(model.getPhone());
            }
            if (isNotEmpty(model.getRealAmount())) {
                entity.setRealAmount(model.getRealAmount());
            }
            if (isNotEmpty(model.getStatus())) {
                entity.setStatus(model.getStatus());
            }
            if (isNotEmpty(model.getCreateDate())) {
                entity.setCreateDate(model.getCreateDate());
            }
            model = entity2model(dao.save(entity));
        }
        return model;
    }

    @Override
    public DaiFuOrder send(DaiFuOrder model) {
        model = super.findById(model.getId());
        DdjDaiFuOrder ddjDaiFuOrder = model2Entity(model);
        DdjDfBusiness ddjDfBusiness = busniessDao.findOne(model.getDfBusinessId());
        DdjUser user = userDao.findOne(model.getUserId());
        ddjDaiFuOrder.setStatus(StatusDict.NORMAL);
        dao.save(ddjDaiFuOrder);
        if (StatusDict.DELETE.equals(ddjDfBusiness.getStatus())) {
            throw new BaseException("此代付通道已停用");
        }
        switch (ddjDfBusiness.getName()) {
            case "msf":
                msf(ddjDaiFuOrder, user, ddjDfBusiness);
                break;
            case "JDF":
                jdf(ddjDaiFuOrder, user, ddjDfBusiness);
                break;
            case "YL":
                YL(ddjDaiFuOrder, user, ddjDfBusiness);
                break;
            default:
                throw new BaseException("没有可用通道");

        }
        DaiFuOrder daiFuOrder = entity2model(ddjDaiFuOrder);

        return daiFuOrder;
    }

    private void YL(DdjDaiFuOrder ddjDaiFuOrder, DdjUser user, DdjDfBusiness ddjDfBusiness) {
        //Date date =new Date();
        //ddjDfBusiness用户
        //ddjDaiFuOrder订单
        System.out.println(ddjDaiFuOrder);
        //SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMss");
        Map<String, String> map = new HashMap();
        String total_amount = ddjDaiFuOrder.getAmount().toString();
        if (ddjDaiFuOrder.getAmount().toString().indexOf(".00") == -1) {
            total_amount = total_amount + ".00";
        }
        map.put("total_amount", total_amount);//代付金额
        map.put("out_transfer_no", ddjDaiFuOrder.getOrderNo());//代付单号
        map.put("bank_name", ddjDaiFuOrder.getBank());//代付银行名称
        map.put("sub_bank_address", ddjDaiFuOrder.getBackup2() + ddjDaiFuOrder.getBackup3());//支行地址
        map.put("payee", ddjDaiFuOrder.getPerson());//收款人
        map.put("bank_card_no", ddjDaiFuOrder.getCardNo());//银行卡号
        map.put("security_code", ddjDfBusiness.getBackup1());//代付安全码
        map.put("appid", ddjDfBusiness.getAccount());//代付商户id
        map.put("request_time", DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        //map.put("request_time",sdf.format(date));//时间
        map.put("version", "1.0.0");//版本号
        System.out.println(map);

        /*String res=HttpUtils.post("http://npay.elongpay.com/withdraw/create", com.qian.api.ddj.util.SignUtils.params(map));
        JSONObject jb = JSON.parseObject(res);*/
        String reqUrl = "http://npay.elongpay.com/withdraw/create";

        String res = null;
        try {
            map.put("sign", ApiUtils.getSign(map, ddjDfBusiness.getSecretKey()));
            System.out.println("=============>");
            HttpPost httpPost = new HttpPost(reqUrl);
            StringEntity stringEntity = new StringEntity(JsonUtils.toJson(map), "UTF-8");
            stringEntity.setContentType("application/json");
            httpPost.setEntity(stringEntity);
            String result = HttpClientUtils.execute(httpPost);
            JSONObject resultMap = JSONObject.parseObject(result);
            System.out.println(result);
            if ("0".equals(resultMap.get("code"))) {
                if ("10010".equals(resultMap.getString("biz_code"))) {
                    System.out.println("<===========>");
                    ddjDaiFuOrder.setStatus(StatusDict.SUCCESS);//状态
                    ddjDaiFuOrder.setUpOrderNo(resultMap.getString("transfer_no"));
                    System.out.println("代付成功" + "=======");
                    ddjDaiFuOrder.setFinishDate(new Date());
                    dao.save(ddjDaiFuOrder);
                    user.setBalance(new BigDecimal(user.getBalance().doubleValue() - ddjDaiFuOrder.getRealAmount().doubleValue()));//查询余额
                    userDao.save(user);
                    userService.unLockMoney(user.getId(), ddjDaiFuOrder.getRealAmount());
                } else {
                    ddjDaiFuOrder.setStatus(StatusDict.FAIL);
                    ddjDaiFuOrder.setFinishDate(new Date());
                    userService.unLockMoney(user.getId(), ddjDaiFuOrder.getRealAmount());
                    dao.save(ddjDaiFuOrder);
                }
            } else {
                ddjDaiFuOrder.setStatus(StatusDict.FAIL);
                ddjDaiFuOrder.setFinishDate(new Date());
                userService.unLockMoney(user.getId(), ddjDaiFuOrder.getRealAmount());
                dao.save(ddjDaiFuOrder);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }


    private void jdf(DdjDaiFuOrder ddjDaiFuOrder, DdjUser user, DdjDfBusiness ddjDfBusiness) {
        Date date = new Date();
        System.out.println(ddjDaiFuOrder);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        Map<String, String> map = new TreeMap();
        map.put("service", "trade.payment");
        map.put("version", "1.0");//版本
        map.put("merchantId", ddjDfBusiness.getAccount());//商户
        map.put("orderNo", ddjDaiFuOrder.getOrderNo());//订单
        map.put("tradeDate", sdf.format(date));
        map.put("tradeTime", "123015");
        String amount1 = String.valueOf((int) (ddjDaiFuOrder.getAmount().multiply(new BigDecimal(100)).doubleValue()));
        map.put("amount", amount1);//金额
        map.put("bankCode", ddjDaiFuOrder.getBank());
        map.put("benAcc", ddjDaiFuOrder.getCardNo());
        map.put("benName", ddjDaiFuOrder.getPerson());
        map.put("bankBranchName", ddjDaiFuOrder.getBackup1());
        map.put("province", ddjDaiFuOrder.getBackup2());
        map.put("city", ddjDaiFuOrder.getBackup3());
        map.put("release", "1");
        map.put("cellPhone", ddjDaiFuOrder.getPhone());
        map.put("accType", "1");
        map.put("release", "1");
        map.put("clientIp", "127.0.0.1");
        map.put("notifyUrl", "http://localhost/response.html");
        map.put("sign", createSign(map, ddjDfBusiness.getSecretKey()));
        System.out.println(map);
        String reqUrl = "https://paygw.pk10000.com/gateway";

        CloseableHttpResponse response = null;
        CloseableHttpClient client = null;
        String res = null;
        try {
            HttpPost httpPost = new HttpPost(reqUrl);
            List<NameValuePair> nvps = new ArrayList();
            for (String k : map.keySet()) {
                nvps.add(new BasicNameValuePair(k, map.get(k)));
            }
            httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
            httpPost.addHeader("Connection", "close");
            client = HttpClient.createHttpClient();
            response = client.execute(httpPost);
            if (response != null && response.getEntity() != null) {
                String content = EntityUtils.toString(response.getEntity(), "UTF-8");
                Map<String, String> resultMap = SignUtils.parseQuery(content);
                System.out.println(resultMap);
                if ("0001".equals(resultMap.get("repCode"))) {
                    ddjDaiFuOrder.setStatus(StatusDict.SUCCESS);//状态
                    ddjDaiFuOrder.setFinishDate(new Date());
                    dao.save(ddjDaiFuOrder);
                    user.setBalance(new BigDecimal(user.getBalance().doubleValue() - ddjDaiFuOrder.getRealAmount().doubleValue()));//查询余额
                    userDao.save(user);
                    userService.unLockMoney(user.getId(), ddjDaiFuOrder.getRealAmount());

                } else {
                    ddjDaiFuOrder.setStatus(StatusDict.FAIL);
                    ddjDaiFuOrder.setFinishDate(new Date());
                    userService.unLockMoney(user.getId(), ddjDaiFuOrder.getRealAmount());
                    dao.save(ddjDaiFuOrder);
                }

            }

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public DaiFuOrder submit(WithdrawModel model) {
        DdjUser user = new DdjUser();
        user.setUsername(model.getUserId());
        user = userDao.findOne(Example.of(user));
        DdjDaiFuOrder ddjDaiFuOrder = new DdjDaiFuOrder();

        DdjDfBusiness dfBusiness = null;
        Double amount = null;
        if (isNotEmpty(user.getDfBusinessId())) {
            dfBusiness = busniessDao.findOne(user.getDfBusinessId());
            amount = model.getAmount().doubleValue() + user.getDfFee().doubleValue();
            if (!(dfBusiness.getBeginMoney().doubleValue() < amount)) {
                throw new BaseException("小于最低代付金额");
            } else if (!(dfBusiness.getEndMoney().doubleValue() > amount)) {
                throw new BaseException("大于最大代付金额");

            } else {
                dfBusiness = busniessDao.findOne(user.getDfBusinessId());
                ddjDaiFuOrder.setOrderNo(user.getId() + model.getOutOrderNo());
                ddjDaiFuOrder.setStatus(StatusDict.PENDING);
                ddjDaiFuOrder.setRealAmount(new BigDecimal(amount));
                ddjDaiFuOrder.setPerson(model.getPerson());
                ddjDaiFuOrder.setAmount(model.getAmount());
                ddjDaiFuOrder.setPhone(model.getPhone());
                ddjDaiFuOrder.setOutOrderNo(model.getOutOrderNo());
                ddjDaiFuOrder.setCardNo(model.getCardNo());
                ddjDaiFuOrder.setBank(model.getBank());
                ddjDaiFuOrder.setDdjBusiness(dfBusiness);
                ddjDaiFuOrder.setDdjUser(user);
                ddjDaiFuOrder.setBackup1(model.getBankBranchName());//支行名称
                ddjDaiFuOrder.setBackup2(model.getProvince());//开户省
                ddjDaiFuOrder.setBackup3(model.getCity());//开户市
                userService.lockMoney(user.getId(), ddjDaiFuOrder.getRealAmount());
                if (user.getBalance().doubleValue() > ddjDaiFuOrder.getAmount().doubleValue()) {
                    ddjDaiFuOrder = dao.save(ddjDaiFuOrder);
                } else {
                    throw new BaseException("余额不足！");
                }
            }
        } else {
            throw new BaseException("没有可用代付通道");
        }

        if (StatusDict.NORMAL.equals(user.getIsAutoDf())) {
            send(entity2model(ddjDaiFuOrder));
        }
        return entity2model(ddjDaiFuOrder);
    }

    private DdjDaiFuOrder msf(DdjDaiFuOrder daiFuOrder, DdjUser user, DdjDfBusiness dfBusiness) {

        return daiFuOrder;

    }

    @Override
    public User query(String username) {
        User ddjUser = new User();
        ddjUser.setUsername(username);
        return userService.findOne(ddjUser);
    }

    @Override
    protected BaseRepository getDao() {
        return dao;
    }

    @Override
    protected DdjDaiFuOrder model2Entity(DaiFuOrder model) {
        DdjDaiFuOrder entity = null;
        if (isNotEmpty(model)) {
            entity = new DdjDaiFuOrder();
            entity.setId(model.getId());
            entity.setAmount(model.getAmount());
            entity.setBackup1(model.getBackup1());
            entity.setBackup2(model.getBackup2());
            entity.setBackup3(model.getBackup3());
            entity.setBackup4(model.getBackup4());
            entity.setBackup5(model.getBackup5());
            entity.setPerson(model.getPerson());
            entity.setPhone(model.getPhone());
            entity.setStatus(model.getStatus());
            entity.setBank(model.getBank());
            entity.setCardNo(model.getCardNo());
            entity.setCreateDate(model.getCreateDate());
            entity.setOutOrderNo(model.getOutOrderNo());
            entity.setUpOrderNo(model.getUpOrderNo());
            entity.setOrderNo(model.getOrderNo());
            entity.setFinishDate(model.getFinishDate());
            entity.setRealAmount(model.getRealAmount());
            if (isNotEmpty(model.getUserId())) {
                DdjUser ddjUser = new DdjUser();
                ddjUser.setId(model.getUserId());
                entity.setDdjUser(ddjUser);
            }
            if (isNotEmpty(model.getDfBusinessId())) {
                DdjDfBusiness business = new DdjDfBusiness();
                business.setId(model.getDfBusinessId());
                entity.setDdjBusiness(business);
            }

        }
        return entity;
    }

    @Override
    protected DaiFuOrder entity2model(DdjDaiFuOrder entity) {
        DaiFuOrder model = null;
        if (isNotEmpty(entity)) {
            model = new DaiFuOrder();
            model.setId(entity.getId());
            model.setPerson(entity.getPerson());
            model.setAmount(entity.getAmount());
            model.setCardNo(entity.getCardNo());
            model.setBackup1(entity.getBackup1());
            model.setBackup2(entity.getBackup2());
            model.setBackup3(entity.getBackup3());
            model.setBackup4(entity.getBackup4());
            model.setBackup5(entity.getBackup5());
            model.setBank(entity.getBank());
            model.setCreateDate(entity.getCreateDate());
            model.setFinishDate(entity.getFinishDate());
            model.setOutOrderNo(entity.getOutOrderNo());
            model.setOrderNo(entity.getOrderNo());
            model.setUpOrderNo(entity.getUpOrderNo());
            model.setStatus(entity.getStatus());
            model.setAmount(entity.getAmount());
            model.setRealAmount(entity.getRealAmount());
            model.setPhone(entity.getPhone());
            if (isNotEmpty(entity.getDdjBusiness())) {
                model.setDfBusinessId(entity.getDdjBusiness().getId());
            }
            if (isNotEmpty(entity.getDdjUser())) {
                model.setUserId(entity.getDdjUser().getId());
            }

        }
        return model;
    }
}
